home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / linux_bo / netboot.zoo / newdrive / net503.asm < prev    next >
Encoding:
Assembly Source File  |  1993-04-21  |  21.3 KB  |  1,014 lines

  1. ;  3C503 Driver
  2. ;
  3. ;    Kurt Mahan ( based on WD8003 by Tim Krauskopf )
  4. ;
  5. ;****************************************************************************
  6. ;*                                                                          *
  7. ;*                                                                          *
  8. ;*      part of NCSA Telnet                                                 *
  9. ;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  10. ;*        neat other things by Kurt Mahan
  11. ;*                                                                          *
  12. ;*      National Center for Supercomputing Applications                     *
  13. ;*      152 Computing Applications Building                                 *
  14. ;*      605 E. Springfield Ave.                                             *
  15. ;*      Champaign, IL  61820                                                *
  16. ;*                                                                          *
  17. ;*                                                                          *
  18. ;****************************************************************************
  19. ;
  20.  
  21.     TITLE    NETSUPPORT -- LOW LEVEL DRIVERS FOR ETHERNET
  22. ;
  23. ;  Assembler support for interrupt-driven Ethernet I/O on the PC
  24. ;
  25. ;  Reads and writes from the 8K buffer on the WD card.
  26. ;  Started 4/11/88
  27. ;
  28.     include model.inc
  29.  
  30.         NAME    NET503
  31.  
  32. ;
  33. ;    EQUATES for the 3C503 board
  34. ;
  35.  
  36. CMDR    equ    00h              ; ports on the 8390 ( page 0 )
  37. PSTART    equ    01h
  38. PSTOP    equ    02h
  39. BNRY    equ    03h
  40. TPSR    equ    04h
  41. TBCR0    equ    05h
  42. TBCR1    equ    06h
  43. ISR    equ    07h
  44. RSAR0    equ    08h
  45. RSAR1    equ    09h
  46. RBCR0    equ    0ah
  47. RBCR1    equ    0bh
  48. XRCR    equ    0ch
  49. TCR    equ    0dh
  50. DCR    equ    0eh
  51. IMR    equ    0fh
  52.  
  53. PAR0    equ    01h              ; ports on the 8390 ( page 1 )
  54. PAR1    equ    02h
  55. PAR2    equ    03h
  56. PAR3    equ    04h
  57. PAR4    equ    05h
  58. PAR5    equ    06h
  59. CURR    equ    07h
  60. MAR0    equ    08h
  61. MAR1    equ    09h
  62. MAR2    equ    0ah
  63. MAR3    equ    0bh
  64. MAR4    equ    0ch
  65. MAR5    equ    0dh
  66. MAR6    equ    0eh
  67. MAR7    equ    0fh
  68.  
  69. PSTR    equ    400h              ; ports on the gate array
  70. PSPR    equ    401h
  71. DQTR    equ    402h
  72. BCFR    equ    403h
  73. PCFR    equ    404h
  74. GACFR    equ    405h
  75. CTRL    equ    406h
  76. STREG    equ    407h
  77. IDCFR    equ    408h
  78. DAMSB    equ    409h
  79. DALSM    equ    40ah
  80. VPTR2    equ    40bh
  81. VPTR1    equ    40ch
  82. VPTR0    equ    40dh
  83. RFMSB    equ    40eh
  84. RFLSB    equ    40fh
  85.  
  86. STRT_PG    equ    26h              ; start at page 6
  87. STOP_PG    equ    40h              ; end at page 31
  88. TSTRT_PG equ    20h              ; transmit start page
  89.  
  90. ;
  91. ;  macros for writing to NET503 board
  92. ;
  93. ;***********************************************************************
  94. ;
  95. ;    Macros, from example driver
  96. ;
  97. ;***********************************************************************
  98.  
  99. ;
  100. ; MACRO rd_wd8
  101. ;   Reads port specified on macro call. Leaves byte in AL.
  102. ;
  103.  
  104. rd_wd8    MACRO    port
  105.     push    dx
  106.     mov    DX, WDBASE
  107.     add    DX, port        ; DX contains address of port
  108.     in    AL, DX            ; AL contains data read from port
  109.     pop    dx
  110.     ENDM
  111.  
  112. ;
  113. ; MACRO wr_wd8
  114. ;   Writes byte in AL to port specified on macro call.
  115. ;
  116.  
  117. wr_wd8    MACRO    port
  118.     push    dx
  119.     mov    DX, WDBASE
  120.     add    DX, port        ; DX contains address of port
  121.     out    DX, AL            ; AL contains data to be written to port
  122.     pop    dx
  123.     ENDM
  124.  
  125. ;
  126. ifdef Microsoft
  127. ;DGROUP    group    _DATA
  128. ;_DATA    segment    public 'DATA'
  129. ;    assume    DS:DGROUP
  130.     .data
  131. else
  132.     DSEG
  133. endif
  134. ;    PUBLIC    STAT,BUFPT,BUFORG,BUFEND,BUFREAD,BUFBIG,BUFLIM,OFFS
  135. ;
  136. ;  The pointers below are actually DWORDs but we access them two
  137. ;  bytes at a time.
  138. ;
  139. ; STAT change to RSTAT because of name clash with MSC library routine
  140. ifdef Microsoft
  141.     EXTRN    _RSTAT:BYTE    ; last status from read
  142.     EXTRN    _BUFPT:WORD    ; current buffer pointer
  143.     EXTRN    _BUFORG:WORD    ; pointer to beginning of buffer
  144.     EXTRN    _BUFEND:WORD    ; pointer to end of buffer
  145.     EXTRN    _BUFREAD:WORD    ; pointer to where program is reading
  146.     EXTRN    _BUFBIG:WORD    ; integer, how many bytes we have
  147.     EXTRN    _BUFLIM:WORD    ; integer, max bytes we can have
  148. else
  149.     EXTRN    RSTAT:BYTE    ; last status from read
  150.     EXTRN    BUFPT:WORD    ; current buffer pointer
  151.     EXTRN    BUFORG:WORD    ; pointer to beginning of buffer
  152.     EXTRN    BUFEND:WORD    ; pointer to end of buffer
  153.     EXTRN    BUFREAD:WORD    ; pointer to where program is reading
  154.     EXTRN    BUFBIG:WORD    ; integer, how many bytes we have
  155.     EXTRN    BUFLIM:WORD    ; integer, max bytes we can have
  156. endif
  157.  
  158. WDBASE    DW    00h        ; base ioaddr
  159. WDADD    DW    00h        ; base shared mem addr
  160. DEAF    DB    00H        ; when we can't handle any more packets
  161. OFFS    DW    00H        ; how many times the handler was turned off
  162. WIRE    DB    02h        ; thin as the default
  163. ;
  164. ifdef Microsoft
  165. ;_DATA    ends
  166. else
  167.     ENDDS
  168. endif
  169. ;
  170. ;   The subroutines to call from C
  171. ;
  172. ifdef Microsoft
  173. ;_TEXT    segment    public    'CODE'
  174. ;    assume CS:_TEXT
  175.     .code
  176.     PUBLIC    _E4RECV,_E4ETOPEN,_E4ETCLOSE,_E4GETADDR
  177.     PUBLIC    _E4SETADDR,_E4XMIT,_E4ETUPDATE
  178.     PUBLIC _E4SETWIRE
  179. else
  180.     PSEG
  181.     PUBLIC    E4RECV,E4ETOPEN,E4ETCLOSE,E4GETADDR
  182.     PUBLIC    E4SETADDR,E4XMIT,E4ETUPDATE, E4SETWIRE
  183. endif
  184.  
  185.  
  186. ;*****************************************************************
  187. ;
  188. ; E4SETWIRE
  189. ;
  190. ; WHAT TYPE OF WIRE ARE WE USING?  THIN OR THICK
  191. ;
  192. ; USAGE: E4SETWIRE(INT WIRE)
  193. ;
  194. START_PROC E4SETWIRE
  195.  
  196.     PUSH BP
  197.     MOV  BP,SP
  198.     push ds
  199.  
  200.     GET_DS_SEG WIRE
  201.  
  202.     XOR  AX,AX
  203.     MOV  AL,[BP+X]        ; GET WIRE TYPE
  204.     MOV  WIRE,AL         ; STORE IT!
  205.     pop  ds
  206.     POP  BP
  207.     RET
  208.  
  209. END_PROC E4SETWIRE
  210.  
  211. ;******************************************************************
  212. ;  ETOPEN
  213. ;     Initialize the Ethernet board, set receive type.
  214. ;
  215. ;  usage:  etopen(s,irq,addr,ioaddr)
  216. ;           char s[6];       ethernet address
  217. ;           int irq,addr,ioaddr;     
  218. ;                interrupt number (unused), base mem address and
  219. ;                i/o address to use
  220. ;
  221. START_PROC E4ETOPEN
  222.  
  223. ;
  224. ;    init addresses and things
  225. ;
  226.  
  227.     PUSH    BP
  228.     MOV    BP,SP
  229.  
  230.     mov    AX,[BP+X+8]        ; install ioaddr
  231.     mov    WDBASE,AX
  232.     mov    AX,[BP+X+6]        ; install shared mem addr
  233.     mov    WDADD,AX
  234. ;
  235. ;    initialize the gate array
  236. ;
  237.     push    ds
  238.  
  239.     GET_DS_SEG WIRE
  240.  
  241.     mov    al,1            ; reset the board -- onboard xcvr
  242.     or     al,WIRE
  243.     wr_wd8    CTRL
  244.     mov    al,0            ; done with reset -- still onboard xcvr
  245.     or    al,WIRE
  246.     wr_wd8    CTRL
  247.     wr_wd8    CTRL
  248.     pop    ds
  249. ;
  250. ;    set the vector pointers ( VPTR0 - VPTR2 ) so that the shared memory
  251. ;    won't go byebye on us accidentally ( point to ffff00h )
  252. ;
  253.     mov    al,0ffh
  254.     wr_wd8    VPTR2
  255.     wr_wd8    VPTR1
  256.     xor    al,al
  257.     wr_wd8    VPTR0
  258. ;
  259. ;    lookup the shared memory address ( such a neat card, huh -- we can
  260. ;    actually read it up from the gate array )
  261. ;
  262. ;    PCFR : high bits = ( 7 .. 0 )
  263. ;                bit 7 = dc00
  264. ;                bit 6 = d800
  265. ;                bit 5 = cc00
  266. ;                bit 4 = c800
  267. ;
  268. ;
  269.     rd_wd8    PCFR            ; read prom config register
  270.     test    al,80h            ; dc00?
  271.     jz    eto100
  272.     mov    WDADD,0da00h
  273.     jmp SHORT etok
  274. eto100:    test    al,40h            ; d800?
  275.     jz    eto200
  276.     mov    WDADD,0d600h
  277.     jmp SHORT etok
  278. eto200:    test    al,20h            ; cc00?
  279.     jz    eto300
  280.     mov    WDADD,0ca00h
  281.     jmp SHORT etok
  282. eto300:    test    al,10h            ; c800?
  283.     jz    eto400
  284.     mov    WDADD,0c600h
  285.     jmp SHORT etok
  286. ;
  287. eto400:    mov    ax,-1            ; mem not enabled
  288.     pop    bp
  289.     ret
  290. ;
  291. ;    ok, WDBASE is setup as the base memory address
  292. ;
  293. etok :    mov    al,0c9h            ; dis ints, ram sel, bank 0
  294.     wr_wd8    GACFR
  295. ;
  296. ;    setup the start/stop pages 
  297. ;
  298.     mov    al,STRT_PG        ; starting page
  299.     wr_wd8    PSTR
  300.     mov    al,STOP_PG        ; ending page
  301.     wr_wd8    PSPR
  302. ;
  303. ;    setup the interrupt and dma request stuff
  304. ;
  305.     xor    al,10h            ; no ints, no dma channels
  306.     wr_wd8    IDCFR            ; interrupt/dma channel ctrl
  307. ;
  308. ;    set DRQ timer to 8
  309. ;
  310.     mov    al,8
  311.     wr_wd8    DQTR
  312. ;
  313. ;    set dma msb to 20h
  314. ;
  315.     mov    al,TSTRT_PG        ; transmit start page
  316.     wr_wd8    DAMSB
  317.     xor    al,al            ; 0
  318.     wr_wd8    DALSM
  319. ;
  320.     cld
  321. ;
  322. ; initialize the LAN Controller register
  323. ;                    
  324.     push    ds
  325.     mov    ax,seg WIRE
  326.     mov    ds,ax
  327.     mov    al,0
  328.     or    al,WIRE
  329.     wr_wd8    CTRL            ; make sure its switched in
  330.     pop    ds
  331. ;
  332. ; program for page 0
  333. ;
  334.     mov    AL, 21h              ; page 0, abort any pending dma
  335.     wr_wd8    CMDR
  336. ;
  337. ;    clear interrupt regs
  338. ;
  339.     mov    al, 0ffh
  340.     wr_wd8    ISR
  341. ;
  342. ; initial DCR data configuration
  343. ;
  344.     mov    AL, 48h               ; burst dma, fifo thresh = 8 bytes
  345.     wr_wd8    DCR
  346. ;
  347. ; initial TCR
  348. ;
  349.     xor    AL, AL            
  350.     wr_wd8    TCR            ; normal operation
  351. ;
  352. ; initial RCR to monitor mode
  353. ;
  354.     mov    AL, 20h                ; monitor mode
  355.     wr_wd8    XRCR
  356. ;
  357. ; set page start/page stop/ boundary
  358. ;
  359.     mov    AL,STRT_PG
  360.     wr_wd8    PSTART
  361.     mov    al,STOP_PG
  362.     wr_wd8    PSTOP
  363.     mov    al,STRT_PG        ; go with the WD style of things
  364.     wr_wd8    BNRY
  365. ;
  366. ; program for page 1
  367. ;
  368.     mov    AL, 60h               ; page 1, abort any pending dma
  369.     wr_wd8    CMDR
  370. ;
  371. ; initial physical addr
  372. ;
  373.     mov    DX, WDBASE        ; get board io base
  374.     push    DS
  375.  
  376.     mov    ax,[bp+X+2]        ; get seg from parms
  377.     mov    ds,ax
  378.  
  379.     mov    CX, 6            ; should be 6 for Ethernet
  380.     mov    BX, [BP+X]        ; ptr to adr in BX
  381.     add    DX, PAR0        ; i/o address of PAR0 in DX
  382. lopa:
  383.     mov    AL, [BX]        ; get 1 byte into AL
  384.     out    DX, AL            ; write to PAR
  385.     inc    BX
  386.     inc    DX
  387.     loop    lopa
  388.     pop    DS
  389. ;
  390. ; initial multicast filter,  write all 0's  into MAR0 - MAR7
  391. ;
  392.     mov    CX, 8
  393.     mov    DX, WDBASE
  394.     add    DX, MAR0        ; i/o address of MAR0 in DX
  395.     xor    AL, AL            
  396. lopb:
  397.     out    DX, AL
  398.     inc    DX
  399.     loop    lopb                    
  400. ;
  401. ;    set CURR page
  402. ;
  403.     mov    al,STRT_PG+1
  404.     wr_wd8    CURR
  405. ;
  406. ; program for page 0
  407. ;
  408.     mov    al,21h            ; page 0, stop any dma stuff
  409.     wr_wd8    CMDR
  410. ;
  411. ; initial IMR
  412. ;
  413.     xor    al,al            ; ***NCSA Telnet does not need interrupts
  414.     wr_wd8    IMR            ; enable interrupt
  415.     mov    al,0ffh
  416.     wr_wd8    ISR
  417. ;
  418. ;    clear byte counts
  419. ;
  420.     xor    AL, AL
  421.     wr_wd8    RBCR0
  422.     wr_wd8    RBCR1
  423. ;    
  424. ; put 8390 on line
  425. ;
  426.     mov    al,22h            ; start up the 8390
  427.     wr_wd8    CMDR
  428. ;
  429. ; program RCR to normal operation (MSK_AB, no MSK_AM)
  430. ;
  431.     mov    al,4                ; accept broadcast packets
  432.     wr_wd8    XRCR
  433. ;
  434.     mov    al,0c9h
  435.     wr_wd8    GACFR
  436. ;
  437. ;    I'm happy to keep GACFR at c9 ( no interrupts )
  438. ;
  439. ;    return NO ERROR
  440. ;
  441.     XOR    AX,AX
  442.     POP    BP
  443.     RET
  444. ;
  445. END_PROC E4ETOPEN
  446. ;
  447. ;******************************************************************
  448. ;  SETADDR
  449. ;    set the Ethernet address on the board to 6 byte ID code
  450. ;
  451. ;   usage:   setaddr(s,basea,ioa);
  452. ;             char s[6];           ethernet address to use
  453. ;             int basea;           shared memory base address 
  454. ;             int ioa;             io address for board
  455. ;
  456. START_PROC E4SETADDR
  457.  
  458.     PUSH    BP
  459.     MOV    BP,SP
  460. ;
  461. ;  not used for this board, set during etopen
  462. ;
  463.     POP    BP
  464.     RET
  465. END_PROC E4SETADDR
  466. ;
  467. ;*******************************************************************
  468. ;  GETADDR
  469. ;     get the Ethernet address off of the board
  470. ;
  471. ;   usage:  getaddr(s,address,ioaddr);
  472. ;    char s[6];           will get six bytes from the PROM
  473. ;       int address;
  474. ;       int ioaddr;      mem address and ioaddress to use
  475. ;
  476. START_PROC E4GETADDR
  477.  
  478.     PUSH    BP
  479.     MOV    BP,SP
  480.     PUSH    DS
  481.     MOV    AX,[BP+X+2]    ; SEG of where to put info
  482.     MOV    DS,AX
  483.     MOV    BX,[BP+X]    ; address of where to put info
  484.     mov    cx,6
  485.     mov    dx,[BP+X+6]    ; ioaddr for board
  486. ;
  487. ;    set the gate array to look at the lower 16 bytes of the prom
  488. ;
  489.     push    ds
  490.  
  491.     GET_DS_SEG WIRE
  492.  
  493.     mov    al,1
  494.     or    al,WIRE
  495.     pop    ds
  496.     push    dx
  497.     add    dx,CTRL
  498.     out    dx,al
  499.     mov    al,2
  500.     out    dx,al
  501.     mov    al,6
  502.     out    dx,al
  503.     
  504.     pop    dx
  505.     push    dx
  506. ;
  507. getloop:
  508.     in    al,dx
  509.     mov    [bx],al        ; store where we want
  510.     inc    dx
  511.     inc    bx
  512.     loop    getloop
  513. ;
  514. ;    reset the gate array to normal mapping
  515. ;
  516.     pop    dx
  517.     push    ds
  518.  
  519.     GET_DS_SEG WIRE
  520.  
  521.     mov    al,0        ; still onboard xcvr 
  522.     or    al,WIRE
  523.     pop    ds
  524.     add    dx,CTRL
  525.     out    dx,al
  526.     POP    DS
  527.     POP    BP        
  528.     RET
  529.  
  530. END_PROC E4GETADDR
  531.  
  532. ;
  533. ;***********************************************************************
  534. ;  ETCLOSE
  535. ;        shut it down, remove the interrupt handler
  536. ;
  537. ;  usage:  etclose();
  538. ;
  539. ;
  540. START_PROC E4ETCLOSE
  541.  
  542.     RET
  543. END_PROC E4ETCLOSE
  544. ;
  545. ;************************************************************************
  546. ;   Receive
  547. ;   This is a CPU hook for boards that must be polled before we can
  548. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  549. ;
  550. ;    usage:  recv();
  551. ;
  552. START_PROC E4RECV
  553.  
  554.     push    bp
  555.     push    es
  556. ;
  557. ;  check for data which can be read
  558. ;
  559.     rd_wd8    XRCR            ; read the Rx Status Register
  560.     and    al,01h            ; check for a packet
  561.     jnz    snore            ; none -- go onto something else
  562.     jmp    end_rx
  563. snore:
  564. ;
  565. ;    ok, the chip thinks we have a packet to read
  566. ;
  567.     mov    AL, 61h            ; page 1
  568.     wr_wd8    CMDR
  569.     rd_wd8    CURR
  570.     mov    BL, AL            ; CURR in BL 
  571. ;
  572.     mov    AL, 20h            ; page 0
  573.     wr_wd8  CMDR
  574.     rd_wd8    BNRY            ; BNRY in AL
  575. ;
  576.     add    AL, 1            ; start page of frm in AL
  577.     cmp    AL, STOP_PG        ; check boundary
  578.     jne    go_cmp
  579.     mov    AL, STRT_PG        
  580. go_cmp:
  581.     cmp    AL, BL            
  582.     jne    gotone
  583.     jmp     end_rx            ; buff ring empty
  584. gotone:
  585. ;
  586. ; ring not empty
  587. ;
  588.     mov    BH, AL
  589.     xor    BL, BL            ; BX has the rx_frm pointer
  590.     push    BX            ; save the frm ptr
  591.         mov    AX, WDADD        ; shared mem base
  592.     mov     ES, AX            ; ES has the shr seg paragraph
  593.     mov    AL, ES:[BX]        ; AL has the status byte
  594. ;    test    AL, SMK_PRX        ; if rx good
  595.     test    al,1
  596.     jnz    readit
  597.     jmp    fd_bnry            ; rx error, drop frm by forward bnry
  598. readit:
  599. ;
  600. ;  set up to read the next packet from the net
  601. ;
  602. ;
  603. ;  get ready for next packet
  604. ;
  605.     cld            ; moves in fwd dir
  606. ;
  607. ;  check for buffer overrun or catching up with reader
  608. ;
  609. ;  implicit 64K max buffer, should stop before 64K anyway
  610. ;
  611. ifdef    Microsoft
  612.     MOV    AX,_BUFBIG    ; how much stuff is in buffer
  613.     MOV    BX,_BUFLIM    ; what is our size limit?
  614. else
  615.     MOV    AX,BUFBIG    ; how much stuff is in buffer
  616.     MOV    BX,BUFLIM    ; what is our size limit?
  617. endif
  618.     CMP    AX,BX
  619.     JNA    ISROOM        ; we are ok
  620. ;
  621. ;  no room at the Inn. 
  622. ;
  623.     JMP SHORT fd_bnry     ; can't do much, we lose packets until restarted
  624.  
  625. ;
  626. ;  wrap pointer around at end, we know that we have room
  627. ;
  628. ISROOM:
  629. ifdef    Microsoft
  630.     MOV    DI,word ptr [_BUFPT]     ; where buffer is
  631.     MOV    DX,word ptr [_BUFEND]    ; right before 2K safety area
  632. else
  633.     MOV    DI,word ptr [BUFPT]     ; where buffer is
  634.     MOV    DX,word ptr [BUFEND]    ; right before 2K safety area
  635. endif
  636.  
  637.     CMP    DX,DI            ; see if pointer is over limit
  638.     JA    OKAYREAD        ; we are not at wrap-around
  639.  
  640. ifdef    Microsoft
  641.     MOV    AX,word ptr [_BUFORG]    ; wrap to here
  642.     MOV    word ptr [_BUFPT],AX    ; wrap-around
  643. else
  644.     MOV    AX,word ptr [BUFORG]    ; wrap to here
  645.     MOV    word ptr [BUFPT],AX    ; wrap-around
  646. endif
  647.     MOV    DI,AX            ; di also
  648.  
  649. OKAYREAD:
  650. ;
  651. ;
  652. ;  start the copy of the new packet
  653. ;  pointer to the shared memory offset is in BX
  654. ;  At this offset, you will find:
  655. ;    1 byte - read status, usually 21h
  656. ;    1 byte - pointer, page # of next packet
  657. ;    2 bytes - length of data in packet, swapped for you already
  658. ;    n bytes - that many bytes of Ethernet packet spread
  659. ;       over n div 256 pages (allowing four lost bytes in first packet)
  660. ;
  661. ;
  662.     pop    si        ; get packet pointer back into si
  663.     push    si        ; restore for fd_bnry to read
  664. ;
  665. ;  save regs while moving packet to buffer
  666. ;  set up ds for buffer, even though we switch it later
  667. ;
  668.     push    es
  669.     push    ds
  670. ifdef    Microsoft
  671.     MOV    AX,word ptr [_BUFPT+2]    ; buffer's ds
  672. else
  673.     MOV    AX,word ptr [BUFPT+2]    ; buffer's ds
  674. endif
  675.     mov    ds,ax
  676. ;
  677. ;  here, DS:DI contains where we want to put the packet.
  678. ;
  679. newpkt:
  680.     add    si,2        ; offset for length field
  681.     mov    dx,es:[si]    ; value of length of recd packet
  682.  
  683.     mov    [di],dx        ; put the accumulated size there
  684.     inc    si
  685.     inc    si
  686.     inc    di
  687.     inc    di        ; now it is the data pointer
  688. ;
  689. ;
  690. ;  Actually move the data
  691. ;    DX has packet size in bytes
  692. ;    ES:SI has the source pointer  } need to switch
  693. ;    DS:DI has the dest pointer    } es and ds
  694. ;    Remember, 256 byte pages wrap around at STOP_PG and there
  695. ;    are max 252 bytes in the first page
  696. ;
  697.     mov    cx,dx
  698.     cmp    cx,252
  699.     jng    shrt
  700.     mov    cx,252        ; first page len
  701. shrt:
  702.     mov    ax,ds
  703.     mov    bx,es
  704.     mov    ds,bx
  705.     mov    es,ax        ; swap them
  706.  
  707.     mov    bx,dx        ; save a copy of data length
  708.  
  709. mvpg:                ; start of page move loop
  710.     sub    dx,cx
  711.     shr    cx,1        ; convert to words
  712.     jnc    iseven
  713.     movsb            ; move odd one if needed
  714. iseven:
  715.     rep    movsw        ; move all words in one page
  716.  
  717.     cmp    dx,0        ; how many left to move?
  718.     jng    donepg
  719.     mov    cx,dx
  720.     cmp    cx,256
  721.     jng    shrtr
  722.     mov    cx,256        ; one more page
  723. shrtr:
  724.     mov    ax,si        ; look at source page
  725.     cmp    ah,STOP_PG
  726.     jl    mvpg
  727.     mov    ah,STRT_PG    ; wrap around at this page boundary
  728.     mov    si,ax        ; put back in si for rest of packet
  729.     jmp    mvpg
  730.  
  731. donepg:
  732.  
  733.     pop    ds
  734.     pop    es        ; put regs back so ES is shared mem
  735.  
  736. ;
  737. ; update the pointer and length in the buffer
  738. ;  DI already points just past end of data just placed there
  739. ;
  740. ifdef    Microsoft
  741.     MOV    word ptr [_BUFPT],di    ; it is here, now
  742.     MOV    AX,word ptr [_BUFBIG]    ; total amount of stuff in buffer
  743. else
  744.     MOV    word ptr [BUFPT],di    ; it is here, now
  745.     MOV    AX,word ptr [BUFBIG]    ; total amount of stuff in buffer
  746. endif
  747.     ADD    AX,BX        ; add in size of this packet
  748.     INC    AX
  749.     INC    AX        ; to cover the length value
  750. ifdef    Microsoft
  751.     MOV    word ptr [_BUFBIG],AX    ; after adding in current packet size
  752. else
  753.     MOV    word ptr [BUFBIG],AX    ; after adding in current packet size
  754. endif
  755. ;
  756. ;
  757. ;  signs that something is actually happening
  758. ;
  759. ;    push    es
  760. ;    MOV    AX,0B000H       ; screen
  761. ;    MOV    ES,AX
  762. ;    MOV    DI,3998        ; lower right corner
  763. ;    INC    cs:ICNT
  764. ;    MOV    al,cs:ICNT    ; character
  765. ;    STOSB
  766. ;    pop    es
  767. ;
  768.  
  769.  
  770. ; drop bad frame by forwarding the BNRY register
  771. ;  or just normal BNRY update after frame read
  772. ;
  773. fd_bnry:                ; drop frm by forward BNRY
  774.     pop    BX            ; restore frm ptr in BX
  775.     add    BX, 1
  776.     mov    AL, ES:[BX]        ; next frm start page in AL
  777.     sub    AL, 1            ; new BNRY in AL
  778.     cmp    AL, STRT_PG        ; check boundary
  779.     jge    wrbnry
  780.     mov    AL, STOP_PG - 1
  781. wrbnry:
  782.     wr_wd8    BNRY
  783.  
  784. end_rx:
  785.     pop    es
  786.     POP    BP
  787.  
  788.     RET            ; for compatibility with other drivers
  789.  
  790. ;ICNT    db    0
  791.  
  792. END_PROC E4RECV
  793.  
  794. ;
  795. ;************************************************************************
  796. ;  XMIT         
  797. ;     send a packet to Ethernet
  798. ;     Is not interrupt driven, just call it when you need it.
  799. ;
  800. ;  usage:   xmit(packet,count)
  801. ;        char *packet;
  802. ;        int count;
  803. ;
  804. ;   Takes a packet raw, Ethernet packets start with destination address,
  805. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  806. ;
  807. ;   checks for packets under the Ethernet size limit of 60 and handles them
  808. ;
  809. START_PROC E4XMIT
  810.  
  811.     PUSH    BP
  812.     MOV    BP,SP
  813.     push    es
  814.     PUSH    DS        ; set up proper ds for the buffer
  815. ;
  816. ;    ok, let's hangout here waiting for the transmitter
  817. ;
  818.     mov    bx,8000h    ; adequate timeout
  819. twait:    rd_wd8    CMDR        ; read up the command reg
  820.     and    al,04h        ; xmit flag
  821.     jz        tfree
  822.     dec    bx
  823.     jnz    twait        ; keep going till timeout
  824.     mov    ax,-1        ; bummer, it hates me
  825.     pop    ds
  826.     pop    es
  827.     pop    bp
  828.     ret
  829. tfree:
  830.     cld
  831. ;
  832.     mov    al,0c9h
  833.     wr_wd8    GACFR
  834. ;
  835.     mov    ax,WDADD    ; shared memory address in ax
  836.     mov    es,ax        ; use es for this
  837. ;
  838. ;  move packet into position, set up regs
  839. ;
  840.     MOV    AX,[BP+X+2]    ; get data ds
  841.     MOV    DS,AX
  842.     MOV    SI,[BP+X]    ; DS:SI points to data buffer
  843.  
  844.     MOV        CX,[BP+X+4]    ; count of bytes
  845.     CMP    CX,60        ; minimum length for Ether
  846.     JNB    OKLEN
  847.     MOV    CX,60        ; make sure size at least 60
  848. OKLEN:
  849. ;
  850. ;  Copy Packet : 
  851. ;
  852. ;    DS:SI = real data
  853. ;    ES    = shared memory address
  854. ;    CX    = number of bytes
  855. ;
  856.     mov    al,0c9h        ; reset the gate array
  857.     wr_wd8    GACFR
  858. ;
  859.     push    cx        ; save xmit length
  860.     xor    ax,ax
  861.     mov    ah,TSTRT_PG    ; starting page number
  862.     mov    di,ax        ; ES:DI = shared mem buff start
  863.     shr    cx,1        ; gonna do 16 bits
  864.     jnc    evenx
  865.     movsb            ; pick up odd byte
  866. evenx:
  867.     rep    movsw        ; copy all data into xmit buf
  868. ;
  869.     mov    al,0
  870.     wr_wd8    TCR
  871. ;
  872. ;  set up xmit length registers
  873. ;
  874.     pop    cx        ; len restored in cx
  875.     pop    ds
  876.     mov    al,cl        ; length
  877.     wr_wd8    TBCR0            ; lower byte to TBCR0
  878.     mov    al,ch
  879.     wr_wd8    TBCR1            ; higher byte to TBCR1
  880. ;
  881. ; set page number
  882. ;
  883.     mov    al,TSTRT_PG
  884.     wr_wd8    TPSR            ; write start page into TPSR
  885. ;
  886. ; issue tx command
  887. ;
  888.     mov    al,24h
  889.     wr_wd8    CMDR            ; start xmit
  890. ;
  891. ;  check to see if the last packet xmitted ok
  892. ;
  893.     xor    cx,cx            ; set a timeout
  894. ;
  895. waitxmit:
  896. ;
  897.     rd_wd8    CMDR        ; command register
  898.     and    al,4        ; xmit bit
  899.     jz    oktogo        ; xmit is finished
  900.     loop    waitxmit    ; waiting for xmit to complete
  901.     mov    ax,-1
  902.     jmp SHORT getout
  903. oktogo:
  904.     xor    ax,ax
  905. ;
  906. ; go back for more
  907. ;
  908. getout:
  909.     pop    es
  910.     POP    BP
  911.     RET
  912. END_PROC E4XMIT
  913.  
  914. ;
  915. ;
  916. ;*************************************************************************
  917. ;  ETUPDATE
  918. ;      update pointers and/or restart receiver when read routine has
  919. ;      already removed the current packet
  920. ;
  921. ;   usage:  etupdate();
  922. ;
  923. START_PROC E4ETUPDATE
  924.  
  925.     PUSH     ES
  926. ifdef    Microsoft
  927.     MOV    AX,word ptr [_BUFPT+2]    ; establish data segment to buffer
  928. else
  929.     MOV    AX,word ptr [BUFPT+2]    ; establish data segment to buffer
  930. endif
  931.     MOV    ES,AX        ; put that in es
  932. ;
  933. ifdef    Microsoft
  934.     MOV    BX,_BUFREAD    ; where read pointer is now
  935. else
  936.     MOV    BX,BUFREAD    ; where read pointer is now
  937. endif
  938.     MOV    DX,ES:[BX]    ; get size of this packet
  939.     INC    DX
  940.     INC    DX        ; two more for length value
  941.  
  942.     ADD    BX,DX        ; increment bufread by size of packet
  943.  
  944. ifdef    Microsoft
  945.     MOV    CX,_BUFEND    ; right before 2K safety area
  946. else
  947.     MOV    CX,BUFEND    ; right before 2K safety area
  948. endif
  949.     CMP    BX,CX        ; see if pointer is over limit
  950.     JB    NOWRAPRD    ; we are not at wrap-around
  951.  
  952. ifdef    Microsoft    
  953.     MOV    BX,_BUFORG    ; wrap to here
  954. NOWRAPRD:
  955.     MOV    _BUFREAD,BX    ; buffer pointer has been updated
  956. else
  957.     MOV    BX,BUFORG    ; wrap to here
  958. NOWRAPRD:
  959.     MOV    BUFREAD,BX    ; buffer pointer has been updated
  960. endif
  961.  
  962. ;
  963. ;  DECREMENT TOTAL BUFFER SIZE
  964. ;
  965.     CLI            ; keep interrupt handler from bothering dec
  966. ifdef    Microsoft
  967.     MOV    CX,_BUFBIG    ; size before removing packet
  968.     SUB    CX,DX        ; remove size of current packet
  969.     MOV    _BUFBIG,CX    ; put it back
  970. else
  971.     MOV    CX,BUFBIG    ; size before removing packet
  972.     SUB    CX,DX        ; remove size of current packet
  973.     MOV    BUFBIG,CX    ; put it back
  974. endif
  975.     STI
  976. ;
  977. ;  IF RECEIVER IS ON, THEN CHECKING BUFLIM IS UNNECESSARY.
  978. ;
  979.     MOV    AL,DEAF        ; is the receiver turned off?
  980.     OR    AL,AL        ; 0 = reading, 1 = deaf
  981.     JZ    ALIVE
  982. ;
  983. ;  CHECK FOR ROOM IN THE BUFFER, IF THERE IS, TURN ON RECEIVER
  984. ;
  985. ifdef    Microsoft
  986.     MOV    AX,_BUFLIM    ; what is our limit?
  987. else
  988.     MOV    AX,BUFLIM    ; what is our limit?
  989. endif
  990.     CMP    CX,AX        ; compare to limit
  991.     JA    ALIVE        ; not really alive, but can't turn on yet
  992.  
  993.     XOR    AL,AL
  994.     MOV    DEAF,AL        ; reset flag
  995.  
  996.     INC    OFFS        ; keep count how many times this happened
  997.  
  998. ;
  999. ;  turn receiver back on
  1000. ;
  1001.  
  1002. ALIVE:
  1003.     POP    ES
  1004.     RET    
  1005.  
  1006. END_PROC E4ETUPDATE
  1007.  
  1008. ifdef Microsoft
  1009. ;_TEXT    ends
  1010. else
  1011.     ENDPS
  1012. endif
  1013.     END
  1014.